package com.youthfilmic.yuejian.util;

import com.youthfilmic.yuejian.conn.RedisConn;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Transaction;

import java.util.List;
import java.util.Set;

/**   
 * Redis操作接口
 *
 * @author 由伟希
 * @version 2015.2.10   
 */
/**
 * @author Dxywx
 *
 */

/**
 * @author Dxywx
 *
 */

//http://blog.csdn.net/tuposky/article/details/45364107 这篇文章是有关批量删除的，写的还不错

public class RedisUtil {
    private static JedisPool pool = null;
    
    /**
     * 构建redis连接池
     * @return JedisPool
     */
    public static JedisPool getPool() {
        if (pool == null) {

            JedisPoolConfig config = new JedisPoolConfig();

            //最大空闲连接数, 默认8个
            config.setMaxIdle(8);

            //最大连接数, 默认8个
            config.setMaxTotal(20);

            //config.set
            //对象空闲多久后逐出, 当空闲时间>该值 且 空闲连接>最大空闲数 时直接逐出,不再根据MinEvictableIdleTimeMillis判断  (默认逐出策略)   
            config.setSoftMinEvictableIdleTimeMillis(1800000);

            //在borrow一个jedis实例时，是否提前进行validate操作；如果为true，则得到的jedis实例均是可用的；
            config.setTestOnBorrow(true);

            if (RedisConn.isFromECS) {
                pool = new JedisPool(config, RedisConn.in, RedisConn.redisPort, 10000, RedisConn.redisPass);
            } else {
                pool = new JedisPool(config, RedisConn.out, RedisConn.redisPort, 10000, RedisConn.redisPass);
            }
        }
            return pool;
    }
    
    /**
     * 返还到连接池
     * 
     * @param pool 
     * @param redis
     */
    public static void returnResource(JedisPool pool, Jedis redis) {
    	 if (redis != null) {
    		 try{
    			 pool.returnResource(redis);
    		 }catch(Exception e){
    			 System.out.println("发生了错误！" + e.getMessage());
    		 }
        }
    }
    
    /**
     * 获取数据
     * 
     * @param key
     * @return
     */
    public static String get(String key){
        String value = null;
        
        JedisPool pool = null;
        Jedis jedis = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            value = jedis.get(key);
            
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }
        return value;
    }
    
    public static Integer getInt(String key){
        String value = null;
        JedisPool pool = null;
        Jedis jedis = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            value = jedis.get(key);
            if (value == null) return 0;
            else return Integer.parseInt(value);
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }
        return 0;
    }
    
    /**
     * 存数据
     * 
     * @param key
     * @param value
     */
    public static void set(String key , String value){
        JedisPool pool = null;
        Jedis jedis = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            jedis.set(key, value);
            
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            returnResource(pool, jedis);
        }   	
    }
    
    /**
     * 存数据
     * 
     * @param key
     * @param value
     */
    public static void set(String key , int second , String value){
        JedisPool pool = null;
        Jedis jedis = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            jedis.setex(key, second, value);
            
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            returnResource(pool, jedis);
        }   	
    }
    
    /**
     * @title 保存对象
     * @instruction 其实就是加了一个序列化的过程
     * @author Dxywx
     * @time 2015.5.13
     * */
    public static void setObject(String key , Object obj){
        JedisPool pool = null;
        Jedis jedis = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            jedis.set(key.getBytes(), SerializeUtil.serialize(obj));
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }   	
    }
    
    /**
     * @title 保存对象
     * @instruction 其实就是加了一个序列化的过程
     * @author Dxywx
     * @time 2015.5.13
     * */
    public static void setObject(String key ,int second, Object obj){
        JedisPool pool = null;
        Jedis jedis = null;
        try {
            pool = getPool();            
            jedis = pool.getResource();
            jedis.setex(key.getBytes(), second, SerializeUtil.serialize(obj));
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }   	
    }
    
    /**
     * @title 获取对象
     * @instruction 其实就是获取之后反序列化
     * @author Dxywx
     * @time 2015.5.13
     * */
    public static Object getObject(String key){
        JedisPool pool = null;
        Jedis jedis = null;
        Object obj = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            obj = SerializeUtil.deserialize(jedis.get(key.getBytes()));
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }
        return obj;
    }
    
    /**
     * @title 删除保存的对象
     * @instruction 清空可以对应的反序列化的byte数组
     * @author Dxywx
     * @time 2015.5.13
     * */
    public static Object deleteObject(String key){
        JedisPool pool = null;
        Jedis jedis = null;
        Object obj = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            jedis.del(key.getBytes());
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }
        return obj;
    }
    
    /**
     * @title 向list添加一个value
     * @instruciton 同上
     * @author Dxywx
     * @time 2015.5.13
     * */
    public static void addToList(String listName , String value){
    	JedisPool pool = null;
        Jedis jedis = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            jedis.lpush(listName, value);
            
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }
    }
    
    /**
     * @title 获取一个list
     * @author Dxywx
     * @time 2015.5.13
     * 
     * */
    public static List<String> getList(String listName){
    	JedisPool pool = null;
        Jedis jedis = null;
        List<String> list = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            list = jedis.lrange(listName, 0, -1);
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }
    	return list;
    }
    
    /**
     * @title 获取list的一部分
     * @param limit start从0开始，limit为截止序号，这样可以获取指定区间的list，不过据说是list很大的时候，获取开头和结尾的部分效率要高
     * @author Dxywx
     * @time 2015.5.13
     * */
    public static List<String> getList(String listName , long start , long limit){
    	JedisPool pool = null;
        Jedis jedis = null;
        List<String> list = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            list = jedis.lrange(listName, start, limit);
            
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }
    	return list;
    }
    
    /**
     * @title 获取list的大小
     * @author Dxywx
     * @time 2015.5.13
     * */
    public static long getListLen(String listName){
    	JedisPool pool = null;
        Jedis jedis = null;
        long len = 0;
        try {
            pool = getPool();
            jedis = pool.getResource();
            len = jedis.llen(listName);
            
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }
    	return len;
    }
    
    
    /**
     * @title 向指定的set里面添加元素
     * @instruction 同上
     * @author Dxywx
     * @time 2015.5.13
     * */
    public static void addToSet(String setName , String value){
    	JedisPool pool = null;
        Jedis jedis = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            jedis.sadd(setName, value);
            
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }
    }
    
    /**
     * @title 判断元素是否在set里面
     * @return true 包含 false 没有包含
     * @author Dxywx
     * @time 2015.5.13
     * */
    public static boolean containsInSet(String setName , String value){
    	JedisPool pool = null;
        Jedis jedis = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            return jedis.sismember(setName, value);
            
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }
        return false;
    }
    
    /**
     * @title 获取set的大小
     * @author Dxywx
     * @time 2015.5.13
     * */
    public static long getSetSize(String setName){
    	JedisPool pool = null;
        Jedis jedis = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            return jedis.scard(setName);
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }
        return 0;
    }
    
    /**
     * @title 从set里面移除value元素
     * @author Dxywx
     * @time 2015.5.13
     * */
    public static void removeFromSet(String setName , String value){
    	JedisPool pool = null;
        Jedis jedis = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            jedis.srem(setName, value);
            
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }
    }
    
    /**
     * @title 获取set
     * @author Dxywx
     * @time 2015.5.13
     * */
    public static Set<String> getSet(String setName){
    	JedisPool pool = null;
        Jedis jedis = null;
        Set<String> set = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            set = jedis.smembers(setName);
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }
    	return set;
    }
    
    /**
     * @title key对应数值的使增
     * @param value value为正值
     * @author Dxywx
     * @time 2015.5.13
     * */
    public static void incrBy(String keyName ,long value){
    	JedisPool pool = null;
        Jedis jedis = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            jedis.incrBy(keyName, value);
            
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }
    }
    
    /**
     * @title key对应数值的使减
     * @param value 为正值
     * @author Dxywx
     * @time 2015.5.13
     * */
    public static void decrBy(String keyName ,long value){
    	JedisPool pool = null;
        Jedis jedis = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            jedis.decrBy(keyName, value); 
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }
    }
    
    
    /**
     * @title 向指定的set添加setValue，然后增减countKeyName
     * @instruction 后边是自增值，原子操作，放心吧
     * @author Dxywx
     * @time 2015.5.12
     * */
    public static void addToSetAndIncrBy(String setName , String setValue , String countKeyName , long num){
    	JedisPool pool = null;
        Jedis jedis = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            Transaction tx = jedis.multi();
            tx.sadd(setName, setValue);
            tx.incrBy(countKeyName, num);
    	    tx.exec();
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }
    }
    
    
    /**
     * @title 向指定的set移除setValue，然后更新countKeyName
     * @instruction 后边是自增值，原子操作，放心吧
     * @author Dxywx
     * @time 2015.5.12
     * */
    public static void removeFromSetAndIncrBy(String setName , String setValue , String countKeyName , long num){
    	JedisPool pool = null;
        Jedis jedis = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            Transaction tx = jedis.multi();
            tx.srem(setName, setValue);
            tx.incrBy(countKeyName, num);
    	    tx.exec();
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }
    }
    
    /**
     * @title 删除key-value对
     * @author Dxywx
     * @time 2015.5.13
     * */
    public static void delete(String key){
    	JedisPool pool = null;
        Jedis jedis = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            jedis.del(key);
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }
    }
    
    /**
     * @title 判断key值是否被包含在Redis数据库中
     * @author Dxywx
     * @time 2015.5.13
     * */
    public static boolean contains(String key){
    	JedisPool pool = null;
        Jedis jedis = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            return jedis.exists(key);
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }
        return false;
    }
    

     /**
     * @author 由伟希
     * @param key 对象对应的key
     * @return 返回Object对象，再强转
     */
    public static boolean containsObjectKey(String key){
    	JedisPool pool = null;
        Jedis jedis = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            return jedis.exists(key.getBytes());
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }
        return false;
    }
    
    
    /**
     * @author 由伟希
     * @param preKey 一组key的前缀
     * @return 返回所有前缀为preKey的所有key
     */
    public static Set<String> getKeySetThroughPre(String preKey){
    	JedisPool pool = null;
        Jedis jedis = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            return jedis.keys(preKey + "*");
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }
        return null;
    }
    
    /**
     * @title 批量删除所有的前缀
     * @param preKey key的前缀
     * @author Dxywx
     * @time 2015.5.31
     * */
    public static void delByPre(String preKey){
    	JedisPool pool = null;
        Jedis jedis = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            Set<String> set = jedis.keys(preKey + "*");
            for (String str : set){
            	jedis.del(str);
            }
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }
        return;
    }

    /**
     * 向里面设置值，如果不存在将被覆盖
     * */
    public static void hashAddToHash(String key , String field , String value){
        JedisPool pool = null;
        Jedis jedis = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            jedis.hset(key, field, value);
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }
        return;
    }

    /**
     * 判断key里面的field是否存在
     * */
    public static boolean hashExist(String key , String field){
        JedisPool pool = null;
        Jedis jedis = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            return jedis.hexists(key, field);
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }
        return false;
    }

    /**
     * 判断key里面的field是否存在
     * */
    public static String hashGet(String key , String field){
        JedisPool pool = null;
        Jedis jedis = null;
        try {
            pool = getPool();
            jedis = pool.getResource();
            return jedis.hget(key, field);
        } catch (Exception e) {
            pool.returnBrokenResource(jedis);
            e.printStackTrace();
        } finally {
            //返还到连接池
            returnResource(pool, jedis);
        }
        return null;
    }
    
    
    public static void main(String[] args){
    	//set("test",10,"youweixi");
    	//System.out.println(contains("test"));
    	//String setName , String setValue , String countKeyName , long num
    	//addToSetAndIncrBy("S","youweixi","001",1);
    	//System.out.println(getSet("S"));
    	//System.out.println(contains("youweix"));
    	//setObject("tt" , new Date());
    	//Date d = (Date)getObject("tt");
    	//System.out.println(d);
        set("lalala",20,"youweixi");
        set("lalala","youweixi2");
        String t = get("lalala");
        System.out.println(t);
    }
    
}
